<?php
namespace TbfDatabase\MysqlAST;

/**
 * 可编程化select命令对象,让sql可以被封装
 */
class SelectCommand{
    /** @var null|SelectExprList  */
    protected $SelectExprList = null;
    /** @var null|TableReferenceList  */
    protected $TableReferenceList = null;
    /** @var null|WhereCondition  */
    protected $WhereCondition = null;
    /** @var null|OrderByList  */
    protected $GroupByList = null;
    /** @var null|WhereCondition  */
    protected $Have = null;
    /** @var null|OrderByList  */
    protected $OrderByList = null;
    /** @var null|Limit  */
    protected $Limit = null;
    protected $IsForUpdate = false;
    protected $IsLockInShareMode = false;
    /** @return SelectCommand */
    static function create(){
        return new SelectCommand();
    }


    /** @return string */
    function GetPrepareSql(){
        $output = 'SELECT ';
        if (empty($this->SelectExprList)){
            $output .= '*';
        }else{
            $output .= $this->SelectExprList->GetText();
        }
        if (!empty($this->TableReferenceList)){
            $output .= ' FROM ';
            $output .= $this->TableReferenceList->GetText();
        }
        if (!empty($this->WhereCondition) && !$this->WhereCondition->IsEmpty() ){
            $output .= ' WHERE '.$this->WhereCondition->GetText();
        }
        if (!empty($this->GroupByList)){
            $output .= ' GROUP BY '.$this->GroupByList->GetText();
        }
        if (!empty($this->Have)){
            $output .= ' HAVE '.$this->Have->GetText();
        }
        if (!empty($this->OrderByList)){
            $output .= ' ORDER BY '.$this->OrderByList->GetText();
        }
        if (!empty($this->Limit)){
            $output .= ' LIMIT '.$this->Limit->GetText();
        }
        if (!empty($this->IsForUpdate)){
            $output .= ' FOR UPDATE ';
        }
        if (!empty($this->IsLockInShareMode)){
            $output .= ' LOCK IN SHARE MODE ';
        }
        return $output;
    }

    /** @return string[] */
    function GetPrepareParameter(){
        $parameters = array();
        if (!empty($this->WhereCondition) && !$this->WhereCondition->IsEmpty() ){
            $parameters = array_merge($parameters,$this->WhereCondition->GetPrepareParameter());
        }
        if (!empty($this->Have)){
            $parameters = array_merge($parameters,$this->Have->GetPrepareParameter());
        }
        return $parameters;
    }

    /** @return SelectCommand */
    function Copy(){
        $obj = new SelectCommand();
        $obj->SelectExprList = self::copyOneNode($this->SelectExprList);
        $obj->TableReferenceList = self::copyOneNode($this->TableReferenceList);
        $obj->WhereCondition = self::copyOneNode($this->WhereCondition);
        $obj->GroupByList = self::copyOneNode($this->GroupByList);
        $obj->Have = self::copyOneNode($this->Have);
        $obj->OrderByList = self::copyOneNode($this->OrderByList);
        $obj->Limit = self::copyOneNode($this->Limit);
        $obj->IsForUpdate = $this->IsForUpdate;
        $obj->IsLockInShareMode = $this->IsLockInShareMode;
        return $obj;
    }

    /** @return SelectCommand */
    function select($text){
        $this->SelectExprList = new StringNodeImpl($text);
        return $this;
    }
    /** @return SelectCommand */
    function from($text){
        $this->TableReferenceList = new StringNodeImpl($text);
        return $this;
    }
    /** @return SelectCommand */
    function where($text,$parameter=array()){
        $this->WhereCondition = new PrepareTextNodeImpl($text,$parameter);
        return $this;
    }
    /** @return SelectCommand */
    function whereObj(WhereCondition $condition){
        $this->WhereCondition = $condition;
        return $this;
    }
    /** @return SelectCommand */
    function groupBy($text){
        $this->GroupByList = new StringNodeImpl($text);
        return $this;
    }
    /** @return SelectCommand */
    function have($text,$parameter=array()){
        $this->Have = new PrepareTextNodeImpl($text,$parameter);
        return $this;
    }
    /** @return SelectCommand */
    function orderBy($text){
        $this->OrderByList = new StringNodeImpl($text);
        return $this;
    }

    /** @return SelectCommand */
    function limit($text){
        $this->Limit = new StringNodeImpl($text);
        return $this;
    }
    /** @return SelectCommand */
    function forUpdate(){
        $this->IsForUpdate = true;
        return $this;
    }
    /** @return SelectCommand */
    function LockInShareMode(){
        $this->IsLockInShareMode = true;
        return $this;
    }

    private static function copyOneNode($node){
        if (!empty($node)){
            return $node->Copy();
        }
        return null;
    }
}
